using System.Net;
using System.Net.Sockets;

using Common;
using Common.NetWork;

using GRPCDemo.Network.Interfaces;
using GRPCDemo.Network.Sockets;
using GRPCDemo.Services;

namespace GRPCDemo.Network
{
    public class NetService
    {
        private SocketListenerBase _listener;
        public string address;
        public int port;

        public NetService(int port) : this("127.0.0.1", port)
        {

        }

        public NetService(string address, int port) : this(address, port, 10)
        {

        }

        public NetService(string address, int port, int backlog)
        {
            this.address = address;
            this.port = port;
            _listener = new TcpSocketListener(address, port, backlog);
            _listener.SocketConnected += OnSocketConnected;
        }

        public void Start()
        {
            Log.Info("Starting Listener...");

            _listener.Start();
            MessageDistributer<NetConnection<NetSession>>.Instance.Start(8);

            Log.Info("NetService Started");
        }

        public void Stop()
        {
            Log.Info("Stop NetService...");

            _listener.Stop();
            MessageDistributer<NetConnection<NetSession>>.Instance.Stop();
        }


        private void OnSocketConnected(object? sender, Socket? e)
        {
            IPEndPoint clientIP = (IPEndPoint)e.RemoteEndPoint;
            //可以在这里对IP做一级验证,比如黑名单

            SocketAsyncEventArgs args = new SocketAsyncEventArgs();
            NetSession session = new NetSession();

            NetConnection<NetSession> connection = new NetConnection<NetSession>(e, args, OnDataReceived, OnDisconnected, session);
            Log.InfoFormat("Client[{0}] Connected", clientIP);
        }

        private void OnDisconnected(NetConnection<NetSession> sender, SocketAsyncEventArgs e)
        {
            if (sender.Session.User != null)
            {
                Log.Info($"OnLoginOut: username:{sender.Session.User.Name}");
                var user = DBService.Instance.Entities.Users.Where(m => m.Name == sender.Session.User.Name).FirstOrDefault();
                if (user != null)
                {
                    user.LoginStatus = false;
                    DBService.Instance.Save();
                }
            }
            Log.InfoFormat("Client[{0}] Disconnected", e.RemoteEndPoint);
        }

        private void OnDataReceived(NetConnection<NetSession> sender, DataEventArgs e)
        {
            //分发数据
            Log.InfoFormat("Client[{0}] DataReceived Len:{1}", e.RemoteEndPoint, e.Length);
            lock (sender.packageHelper)
            {
                sender.packageHelper.ReceiveData(e.Data, 0, e.Data.Length);
            }
        }

    }
}
